package com.leyou.item.service.impl;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.leyou.item.bo.SpuBo;
import com.leyou.item.pojo.*;
import com.leyou.item.mapper.*;
import com.leyou.common.parameter.SpuQueryByPageParameter;
import com.leyou.common.pojo.PageResult;
import com.leyou.item.service.CategoryService;
import com.leyou.item.service.GoodsService;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import tk.mybatis.mapper.entity.Example;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

@Service
public class GoodsServiceImpl implements GoodsService {

    @Resource
    private SpuMapper spuMapper;
    @Resource
    private CategoryService categoryService;
    @Resource
    private BrandMapper brandMapper;
    @Resource
    private SpuDetailMapper spuDetailMapper;
    @Resource
    private SkuMapper skuMapper;
    @Resource
    private StockMapper stockMapper;
    @Autowired
    private AmqpTemplate amqpTemplate;

    private static final Logger LOGGER = LoggerFactory.getLogger(GoodsService.class);

    //发送消息到mq，生产者
    @Override
    public void sendMessage(Long id, String type) {
        try {
            this.amqpTemplate.convertAndSend("item." + type, id);
        } catch (Exception e) {
            LOGGER.error("{}商品消息发送异常，商品id：{}", type, id, e);
        }
    }

    //分页查询商品
    @Override
    public PageResult<SpuBo> querySpuboByPageAndSort(SpuQueryByPageParameter param) {
        //分页
        PageHelper.startPage(param.getPage(), param.getRows());
        //创建查询条件
        Example example = new Example(Spu.class);
        Example.Criteria criteria = example.createCriteria();
        if (param != null) {
            //上下架
            if (param.getSaleable() != null) {
                criteria.orEqualTo("saleable", param.getSaleable());
            }
            //模糊查询
            if (StringUtils.isNotBlank(param.getKey())) {
                criteria.andLike("title", "%" + param.getKey() + "%");
            }
            //排序
            if (StringUtils.isNotBlank(param.getSortBy())) {
                example.setOrderByClause(param.getSortBy() + (param.getDesc() ? " DESC" : " ASC"));
            }
        }
        //查询
        Page<Spu> pageInfo = (Page<Spu>) spuMapper.selectByExample(example);
        //spu转换成spuBo-----java8新特性
        List<SpuBo> list = pageInfo.getResult().stream().map(
                spu -> {
                    //组装spuBo
                    SpuBo spuBo = new SpuBo();
                    //1.属性拷贝
                    BeanUtils.copyProperties(spu, spuBo);
                    //2.查询分类名称
                    List<String> nameList = categoryService.queryNameByIds(Arrays.asList(spu.getCid1(), spu.getCid2(), spu.getCid3()));
                    spuBo.setCname(StringUtils.join(nameList, "/"));
                    //3.查询品牌名称
                    Brand brand = brandMapper.selectByPrimaryKey(spu.getBrandId());
                    spuBo.setBname(brand.getName());
                    return spuBo;
                }
        ).collect(Collectors.toList());
        return new PageResult<>(pageInfo.getTotal(), list);
    }

    //新增商品
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addGoods(SpuBo spu) {
        //添加spu
        spu.setSaleable(true);
        spu.setValid(true);
        spu.setCreateTime(new Date());
        spu.setLastUpdateTime(spu.getCreateTime());
        spuMapper.insert(spu);
        //添加SpuDetail
        SpuDetail spuDetail = spu.getSpuDetail();
        spuDetail.setSpuId(spu.getId());
        spuDetailMapper.insert(spuDetail);
        //添加sku和stock
        saveSkuAndStock(spu.getSkus(), spu.getId());

        //发送消息到mq
        sendMessage(spu.getId(),"insert");
    }


    //商品上下架(单个、批量)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void goodsSoldOutPut(Long id) {
        //操作spu:saleable  sku:enable
        //查询id查询当前oldSpu
        Spu oldSpu = spuMapper.selectByPrimaryKey(id);
        //查询spu对应List<sku>
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("spuId", oldSpu.getId());
        List<Sku> skus = skuMapper.selectByExample(example);
        //判断并修改当前状态
        if (oldSpu.getSaleable()) {
            //1.上架状态
            //下架spu
            oldSpu.setSaleable(false);
            spuMapper.updateByPrimaryKeySelective(oldSpu);
            //下架sku
            for (Sku sku : skus) {
                skuMapper.updateByPrimaryKeySelective(sku);
            }
        } else {
            //2.下架状态
            //上架spu
            oldSpu.setSaleable(true);
            spuMapper.updateByPrimaryKeySelective(oldSpu);
            //上架sku
            for (Sku sku : skus) {
                skuMapper.updateByPrimaryKeySelective(sku);
            }
        }

    }

    //商品删除(单个、批量)
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteGoodsById(String id) {
        //删除spu
        spuMapper.deleteByPrimaryKey(id);
        //删除spu_detail
        spuDetailMapper.deleteByPrimaryKey(id);
        //删除List<sku>
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("spuId", id);
        List<Sku> skus = skuMapper.selectByExample(example);
        for (Sku sku : skus) {
            //删除sku
            skuMapper.deleteByPrimaryKey(sku.getId());
            //删除stock
            stockMapper.deleteByPrimaryKey(sku.getId());
        }
    }

    //商品修改
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateGoods(@RequestBody SpuBo spuBo) {
        //更新spu
        spuBo.setSaleable(true);
        spuBo.setValid(true);
        spuBo.setLastUpdateTime(new Date());
        spuMapper.updateByPrimaryKeySelective(spuBo);

        //更新spuDetail
        SpuDetail spuDetail = spuBo.getSpuDetail();
        spuDetail.setSpuId(spuBo.getId());
        spuDetailMapper.updateByPrimaryKeySelective(spuDetail);

        //判断特有参数spec_template是否修改
        String oldSpecTemplate = spuDetailMapper.selectByPrimaryKey(spuBo.getId()).getSpecTemplate();
        if (spuDetail.getSpecTemplate().equals(oldSpecTemplate)) {
            //相等sku update
            //更新sku和库存信息
            updateSkuAndStock(spuBo.getSkus(), spuBo.getId(), true);
        } else {
            //不等(规格参数修改)，sku insert
            //更新sku和库存信息
            updateSkuAndStock(spuBo.getSkus(), spuBo.getId(), false);
        }
        spuDetail.setSpuId(spuBo.getId());


        //发送消息到mq
        sendMessage(spuBo.getId(),"insert");
    }

    //更新sku和库存信息
    private void updateSkuAndStock(List<Sku> skus, Long id, boolean tag) {
        //通过tag判断是insert还是update
        //获取当前数据库中spu_id = id的sku信息
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("spuId", id);
        //根据spuId查询所有sku
        List<Sku> oldList = skuMapper.selectByExample(example);
        if (tag) {
            /**
             * 判断更新时是否有新的sku被添加：如果对已有数据更新的话，则此时oldList中的数据和skus中的ownSpec是相同的，否则则需要新增
             */
            int count = 0;
            for (Sku sku : skus) {
                //判断是否有新的sku启用
                if (!sku.getEnable()) {
                    continue;
                }

                for (Sku old : oldList) {
                    //规格参数相同
                    if (sku.getOwnSpec().equals(old.getOwnSpec())) {
                        //执行更新
                        List<Sku> list = skuMapper.select(old);
                        if (sku.getPrice() == null) {
                            sku.setPrice(0L);
                        }
                        if (sku.getStock() == null) {
                            sku.setStock((int) 0L);
                        }
                        sku.setId(list.get(0).getId());
                        sku.setCreateTime(list.get(0).getCreateTime());
                        sku.setSpuId(list.get(0).getSpuId());
                        sku.setLastUpdateTime(new Date());
                        skuMapper.updateByPrimaryKeySelective(sku);
                        //更新库存信息
                        Stock stock = new Stock();
                        stock.setSkuId(sku.getId());
                        stock.setStock(sku.getStock());
                        stockMapper.updateByPrimaryKeySelective(stock);
                        //从oldList中将更新完的数据删除
                        oldList.remove(old);
                        break;
                    } else {
                        count++;
                    }
                }
                if (count == oldList.size() && count != 0) {
                    //当只有一个sku时，更新完因为从oldList中将其移除，所以长度变为0，所以要需要加不为0的条件
                    ArrayList<Sku> addSku = new ArrayList<>();
                    addSku.add(sku);
                    saveSkuAndStock(addSku, id);
                    count = 0;
                } else {
                    count = 0;
                }
            }
            //处理脏数据
            if (oldList.size() != 0) {
                for (Sku sku : oldList) {
                    skuMapper.deleteByPrimaryKey(sku.getId());
                    Example example1 = new Example(Stock.class);
                    Example.Criteria criteria1 = example1.createCriteria();
                    criteria1.andEqualTo("skuId", sku.getId());
                    stockMapper.deleteByExample(example1);
                }
            } else {
                List<Long> ids = oldList.stream().map(Sku::getId).collect(Collectors.toList());
                //删除以前的库存
                Example example2 = new Example(Stock.class);
                example.createCriteria().andIn("skuId", ids);
                this.stockMapper.deleteByExample(example2);
                //删除以前的sku
                Example example1 = new Example(Sku.class);
                example1.createCriteria().andEqualTo("spuId", id);
                this.skuMapper.deleteByExample(example1);
                //新增sku和库存
                saveSkuAndStock(skus, id);
            }
        }
    }


    //根据id查询商品信息
    @Override
    @Transactional(rollbackFor = Exception.class)
    public SpuBo queryGoodsBySpuId(Long id) {
        //查询spu
        Spu spu = spuMapper.selectByPrimaryKey(id);
        //查询spuDetail
        SpuDetail spuDetail = spuDetailMapper.selectByPrimaryKey(id);
        //查询List<Sku>
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("spuId", id);
        List<Sku> skus = skuMapper.selectByExample(example);
        //查询stock
        skus.forEach(sku -> {
            Stock stock = stockMapper.selectByPrimaryKey(sku.getId());
            sku.setStock(stock.getStock());
        });
        SpuBo spuBo = new SpuBo();
        //工具类复制属性
        BeanUtils.copyProperties(spu, spuBo);
        spuBo.setSpuDetail(spuDetail);
        spuBo.setSkus(skus);
        return spuBo;
    }

    //新增Sku和Stock
    @Transactional(rollbackFor = Exception.class)
    public void saveSkuAndStock(List<Sku> skus, Long id) {
        for (Sku sku : skus) {
            if (!sku.getEnable()) {
                continue;
            }
            //保存sku
            sku.setSpuId(id);
            sku.setCreateTime(new Date());
            sku.setLastUpdateTime(sku.getCreateTime());
            skuMapper.insertSelective(sku);

            Stock stock = new Stock();
            stock.setSkuId(sku.getId());
            stock.setStock(sku.getStock());
            stockMapper.insertSelective(stock);
        }
    }

    //根据Sku的id查询其下所有的sku
    @Override
    public List<Sku> querySkuBySpuId(Long id) {
        Example example = new Example(Sku.class);
        Example.Criteria criteria = example.createCriteria();
        criteria.andEqualTo("spuId", id);
        List<Sku> skus = skuMapper.selectByExample(example);
        for (Sku sku : skus) {
            Example temp = new Example(Stock.class);
            temp.createCriteria().andEqualTo("skuId", sku.getId());
            Stock stock = this.stockMapper.selectByExample(temp).get(0);
            sku.setStock(stock.getStock());
        }
        return skus;
    }

    //根据skuId查询sku
    @Override
    public Sku querySkuById(Long id) {
        return skuMapper.selectByPrimaryKey(id);
    }

    //根据spu商品id查询详细信息
    @Override
    public SpuDetail querySpuDetailBySpuId(Long id) {
        return this.spuDetailMapper.selectByPrimaryKey(id);
    }

}
